package com.ddxcloud.movie.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ddxcloud.common.constants.ResultStatusConstant;
import com.ddxcloud.common.constants.enums.OrderStatusEnum;
import com.ddxcloud.common.handler.BusinessException;
import com.ddxcloud.movie.config.properties.CommonProperties;
import com.ddxcloud.movie.dto.AddOrderDTO;
import com.ddxcloud.movie.dto.CreateOrderDTO;
import com.ddxcloud.movie.dto.PageDTO;
import com.ddxcloud.movie.entity.Order;
import com.ddxcloud.movie.entity.OrderDetail;
import com.ddxcloud.movie.mapper.OrderMapper;
import com.ddxcloud.movie.service.*;
import com.ddxcloud.movie.vo.AddOrderVO;
import com.ddxcloud.movie.dto.OrderDetailsDTO;
import com.ddxcloud.movie.vo.OrderVO;
import com.ddxcloud.movie.vo.SeatsChangeVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    UserService userService;

    @Resource
    MoviesService moviesService;

    @Resource
    OrderDetailService orderDetailService;

    @Resource
    CommonProperties commonProperties;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Order createOrder(CreateOrderDTO dto) {
        Order order = new Order();
        order.setUserId(userService.getUserByMobile(dto.getMobile()).getUserId());
        String orderSn = DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomNumbers(6);
        order.setOrderSn(orderSn);
        order.setCreateTime(new Date());
        boolean res = this.save(order);
        if (res) {
            AddOrderDTO addOrder = BeanUtil.copyProperties(dto, AddOrderDTO.class);
            addOrder.setOutTradeNo(order.getOrderSn());
            addOrder.setCallbackUrl(commonProperties.getDomainName() + "/order/notify");
            JSONObject jsonObject = moviesService.createOrder(addOrder);
            if (jsonObject.getInteger("code") == 0) {
                try {
                    AddOrderVO vo = JSONUtil.toBean(jsonObject.getString("data"), AddOrderVO.class);
                    order.setAppId(vo.getAppId());
                    order.setOutTradeNo(vo.getOrderNo());
                    order.setOrderAmount(vo.getOrderAmount());
                    order.setOrderStatus(vo.getStatus());
                    res = this.updateById(order);
                    if (res) {
                        OrderDetail orderDetail = new OrderDetail();
                        orderDetail.setOrderId(order.getOrderId());
                        orderDetail.setMobile(dto.getMobile());
                        orderDetail.setFilmId(vo.getFilmId());
                        orderDetail.setFilmName(vo.getFileName());
                        orderDetail.setFilmImg(dto.getFilmImg());
                        orderDetail.setCinemaId(dto.getCinemaId());
                        orderDetail.setCinemaName(dto.getCinemaName());
                        orderDetail.setCinemaAddress(dto.getCinemaAddress());
                        orderDetail.setChangeSeat(dto.getChangeSeat());
                        orderDetail.setShowId(dto.getShowId());
                        orderDetail.setSeats(vo.getSeats());
                        orderDetail.setDeliverMode(dto.getDeliverMode());
                        orderDetail.setStartTime(vo.getStartTime());
                        orderDetail.setEndTime(vo.getEndTime());
                        orderDetailService.save(orderDetail);
                    }
                } catch (Exception e) {
                    log.error("createOrder errMsg: {}", e.getMessage());
                    throw new BusinessException("订单提交失败，请联系管理员");
                }
            } else {
                throw new BusinessException(jsonObject.getString("msg"));
            }
        }
        return order;
    }

    @Override
    public String notify(OrderDetailsDTO dto) {
        log.info("order notify: {}", JSONUtil.toJsonStr(dto));
        Order order = baseMapper.getOrderByOrderSn(dto.getOutTradeNo());
        if (ObjectUtil.isNotEmpty(order)) {
            if (Objects.equals(order.getOrderStatus(), dto.getStatus())
                    && !Objects.equals(dto.getStatus(), OrderStatusEnum.STATUS_2.getCode())
            ) {
                return ResultStatusConstant.SUCCESS;
            }
            LambdaUpdateWrapper<Order> orderUpdate = new LambdaUpdateWrapper<>();
            orderUpdate.set(Order::getOrderStatus, dto.getStatus());
            orderUpdate.set(Order::getSettlementPrice, dto.getOrderAmount());
            orderUpdate.set(Order::getCommission, dto.getCommission());
            orderUpdate.eq(Order::getOrderId, order.getOrderId());
            baseMapper.update(order, orderUpdate);
            if (Objects.equals(dto.getStatus(), OrderStatusEnum.STATUS_2.getCode())) {
                LambdaUpdateWrapper<OrderDetail> detailUpdate = new LambdaUpdateWrapper<>();
                if (null != dto.getSeatsChange()) {
                    StringBuilder stringBuilder = new StringBuilder();
                    List<SeatsChangeVO> list = JSONUtil.toList(dto.getSeatsChange(), SeatsChangeVO.class);
                    for (SeatsChangeVO vo : list) {
                        if (stringBuilder.length() > 0) {
                            stringBuilder.append(",");
                        }
                        stringBuilder.append(vo.getName());
                    }
                    detailUpdate.set(OrderDetail::getRemark, "原座位失效，已替换为：" + stringBuilder);
                }
                detailUpdate.set(OrderDetail::getCodes, dto.getCodes());
                detailUpdate.eq(OrderDetail::getOrderId, order.getOrderId());
                orderDetailService.update(detailUpdate);
            }
            return ResultStatusConstant.SUCCESS;
        }
        return ResultStatusConstant.FAIL;
    }

    @Override
    public IPage<OrderVO> getOrderList(PageDTO dto) {
        Page<OrderVO> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        return baseMapper.getOrderList(page, dto.getUserId());
    }

    @Override
    public OrderVO getOrderInfo(Long orderId) {
        return baseMapper.getOrderInfo(orderId);
    }
}
